// 逻辑
package chess

import (
	"kugo/chess/proto"
	"kugo/log"
	"kugo/utils"
)

type serverControl struct {
}

// 服务逻辑
var ServerControl = &serverControl{}

// 落子 返回值：失败/成功，吃子列表
func (sc *serverControl) DropPieces(point []proto.ChessPoint, piecesType int) (bool, []proto.ChessPoint) {
	pointLen := len(point)
	chessData := ServerModel.ChessData
	var killPoints []proto.ChessPoint = []proto.ChessPoint{}
	if pointLen == 1 { //落子阶段落子
		if chessData[point[0].Row][point[0].Col] != ChessPieces_NONE {
			return false, killPoints
		}
		whiteCount, blackCount := sc.ChessPiecesCount()
		if whiteCount+blackCount < 2 {
			for _, p := range ServerModel.CenterPoint {
				if p.Row == point[0].Row && point[0].Col == p.Col &&
					chessData[point[0].Row][point[0].Col] == ChessPieces_NONE {
					chessData[point[0].Row][point[0].Col] = piecesType
					return true, killPoints
				}
			}
			log.ErrLog("应该落到斜线点")
			return false, killPoints
		} else {
			chessData[point[0].Row][point[0].Col] = piecesType

			return true, killPoints
		}

	} else {
		if chessData[point[1].Row][point[1].Col] != ChessPieces_NONE {
			log.ErrLog("落子地方不为空%s", utils.Struct2JSON(point))
			return false, killPoints
		}
		if ServerModel.CurGameState == GameState_JUMP {
			if len(point) == 2 {
				if point[0].Col == point[1].Col && point[0].Row-point[1].Row == 1 ||
					point[0].Col == point[1].Col && point[0].Row-point[1].Row == -1 ||
					point[0].Row == point[1].Row && point[0].Col-point[1].Col == -1 ||
					point[0].Row == point[1].Row && point[0].Col-point[1].Col == 1 {

					chessData[point[0].Row][point[0].Col] = ChessPieces_NONE
					chessData[point[1].Row][point[1].Col] = piecesType
					return true, killPoints
				}
			}
			for i := 0; i < pointLen-1; i++ {
				tmpKill := sc.JumpKill(point[i], point[i+1], piecesType)
				if len(tmpKill) == 0 {
					log.ErrLog("跳吃不符合规则，%s", utils.Struct2JSON(point))
					return false, []proto.ChessPoint{}
				} else {
					killPoints = append(killPoints, tmpKill[0])
				}
			}
			// 清空吃掉的子
			if len(killPoints) > 0 {
				for i := 0; i < len(killPoints); i++ {
					chessData[killPoints[i].Row][killPoints[i].Col] = ChessPieces_NONE
				}
			}
			chessData[point[0].Row][point[0].Col] = ChessPieces_NONE
			chessData[point[pointLen-1].Row][point[pointLen-1].Col] = piecesType
		} else if ServerModel.CurGameState == GameState_FLY {
			chessData[point[0].Row][point[0].Col] = ChessPieces_NONE
			chessData[point[1].Row][point[1].Col] = piecesType
			return true, killPoints
		} else {
			log.ErrLog("落子失败 状态错误%s", utils.Struct2JSON(point))
		}

	}
	whiteCount, blackCount := sc.ChessPiecesCount()
	if whiteCount <= 13 || blackCount <= 13 {
		ServerModel.CurGameState = GameState_FLY
	}

	return true, killPoints
}

func (sc *serverControl) JumpKill(point1, point2 proto.ChessPoint, piecesType int) []proto.ChessPoint {
	killPoints := []proto.ChessPoint{}
	chessData := ServerModel.ChessData
	if point1.Col == point2.Col {
		if point1.Row-point2.Row == 2 {
			tmpTpye := chessData[point1.Row-1][point1.Col]
			if tmpTpye != piecesType && tmpTpye != ChessPieces_NONE {
				killPoints = append(killPoints, proto.ChessPoint{Col: point1.Col, Row: point1.Row - 1})
				return killPoints
			}
		} else if point1.Row-point2.Row == -2 {
			tmpTpye := chessData[point1.Row+1][point1.Col]
			if tmpTpye != piecesType && tmpTpye != ChessPieces_NONE {
				killPoints = append(killPoints, proto.ChessPoint{Col: point1.Col, Row: point1.Row + 1})
				return killPoints
			}
		}
	} else if point1.Row == point2.Row {
		if point1.Col-point2.Col == 2 {
			tmpTpye := chessData[point1.Row][point1.Col-1]
			if tmpTpye != piecesType && tmpTpye != ChessPieces_NONE {
				killPoints = append(killPoints, proto.ChessPoint{Col: point1.Col - 1, Row: point1.Row})
				return killPoints
			}
		} else if point1.Col-point2.Col == -2 {
			tmpTpye := chessData[point1.Row][point1.Col+1]
			if tmpTpye != piecesType && tmpTpye != ChessPieces_NONE {
				killPoints = append(killPoints, proto.ChessPoint{Col: point1.Col + 1, Row: point1.Row})
				return killPoints
			}
		}
	}
	return killPoints

}

// 棋子数量
func (sc *serverControl) ChessPiecesCount() (int, int) {
	whiteCount, blackCount := 0, 0
	chessData := ServerModel.ChessData
	for row := 0; row < len(chessData); row++ {
		for col := 0; col < len(chessData[row]); col++ {
			if chessData[row][col] == ChessPieces_WHITE {
				whiteCount++
			} else if chessData[row][col] == ChessPieces_BLACK {
				blackCount++
			}
		}
	}
	return whiteCount, blackCount
}

// 游戏结束
func (sc *serverControl) CheckGameEnd() (bool, int) {
	if ServerModel.CurGameState <= GameState_DROP_PIECES {
		return false, ChessPieces_NONE
	}
	whiteCount, blackCount := sc.ChessPiecesCount()

	if whiteCount <= 3 {
		log.Debug("白色棋子<=3,黑胜")
		ServerModel.CurGameState = GameState_GAMEOVER
		return true, ChessPieces_BLACK
	}
	if blackCount <= 3 {
		log.Debug("黑色棋子<=3,白胜")
		ServerModel.CurGameState = GameState_GAMEOVER
		return true, ChessPieces_WHITE
	}

	//校验双褡裢
	_, blackLianCount := sc.SearchDaLian(ChessPieces_BLACK)
	if blackLianCount >= 2 {
		log.Debug("黑色褡裢两个，白胜")
		ServerModel.CurGameState = GameState_GAMEOVER
		return true, ChessPieces_BLACK
	}
	_, whiteLianCount := sc.SearchDaLian(ChessPieces_BLACK)
	if whiteLianCount >= 2 {
		log.Debug("白色褡裢两个，白胜")
		ServerModel.CurGameState = GameState_GAMEOVER
		return true, ChessPieces_WHITE
	}
	return false, ChessPieces_NONE
}

// 久棋寻找褡裢chessData 棋盘数组 1为空位 2为白棋，3为黑棋
// 寻找(row col) (row,col+1),(row+1,col) (row+1,col+1)这四个点(一下简称1,2,3,4点)
// 当这个四为同色棋是，遍历这四个点，例如以1点为中心，遍历1点的上下左右是否为空位置，如果是空位置
// 再找1点相邻的四个直角三点，当有一个直角三点的颜色均与1点相同，且这三点都不与1点相邻(相邻意思是与1点row相同col相差1或者col相同row相差1)，
// 则这个空位点即是褡裢中心点 将这个点存在daLianPoints中，如果这个里面已有这个点，则不存
// daLianPoints = append(daLianPoints, &proto.ChessPoint{Row: row, Col: col})
func (sc *serverControl) SearchDaLian(piecesType int) ([]*proto.ChessPoint, int) {
	if piecesType == ChessPieces_NONE {
		return nil, 0
	}
	daLianPoints := []*proto.ChessPoint{}
	chessData := ServerModel.ChessData
	rows := len(chessData)
	cols := len(chessData[0])

	// 检查是否符合褡裢的条件
	isDaLian := func(row, col int) bool {
		color := chessData[row][col]
		return chessData[row][col+1] == color && chessData[row+1][col] == color && chessData[row+1][col+1] == color
	}

	// 检查周围是否有空位
	isEmpty := func(row, col int) bool {
		if row < 0 || row >= rows || col < 0 || col >= cols {
			return false
		}
		return chessData[row][col] == 1
	}

	// 检查直角三点的颜色是否相同且不与中心点相邻
	checkRightAngle := func(centerRow, centerCol, emptyRow, emptyCol, color int) bool {
		rightAngles := [][3][2]int{
			{{emptyRow - 1, emptyCol}, {emptyRow - 1, emptyCol + 1}, {emptyRow, emptyCol + 1}}, // 上
			{{emptyRow, emptyCol + 1}, {emptyRow + 1, emptyCol + 1}, {emptyRow + 1, emptyCol}}, // 右
			{{emptyRow + 1, emptyCol}, {emptyRow + 1, emptyCol - 1}, {emptyRow, emptyCol - 1}}, // 下
			{{emptyRow, emptyCol - 1}, {emptyRow - 1, emptyCol - 1}, {emptyRow - 1, emptyCol}}, // 左
		}
		for _, points := range rightAngles {
			match := true
			for _, point := range points {
				r, c := point[0], point[1]
				if r < 0 || r >= rows || c < 0 || c >= cols || chessData[r][c] != color {
					match = false
					break
				}
				if r == centerRow && centerCol == c {
					match = false
					break
				}
			}
			if match {
				return true
			}
		}
		return false
	}

	for row := 0; row < rows-1; row++ {
		for col := 0; col < cols-1; col++ {
			if chessData[row][col] != piecesType {
				continue
			}
			if isDaLian(row, col) {
				neighbors := [][2]int{{row, col}, {row + 1, col}, {row, col + 1}, {row + 1, col + 1}}
				for _, neighbor := range neighbors {
					emptyPoints := [][2]int{{neighbor[0] + 1, neighbor[1]}, {neighbor[0] - 1, neighbor[1]}, {neighbor[0], neighbor[1] + 1}, {neighbor[0], neighbor[1] - 1}}
					for _, emptyPoint := range emptyPoints {
						emptyRow, emptyCol := emptyPoint[0], emptyPoint[1]
						if isEmpty(emptyRow, emptyCol) {
							// log.ErrLog("%d,%d", emptyRow, emptyCol)
							if checkRightAngle(neighbor[0], neighbor[1], emptyRow, emptyCol, chessData[row][col]) {
								point := &proto.ChessPoint{Row: emptyRow, Col: emptyCol}
								exists := false
								for _, p := range daLianPoints {
									if p.Row == point.Row && p.Col == point.Col {
										exists = true
										break
									}
								}
								if !exists {
									daLianPoints = append(daLianPoints, point)
								}
							}
						}
					}
				}
			}
		}
	}
	return daLianPoints, len(daLianPoints)
}

// 校验是否形成田子 褡裢吃子
// 校验以最后落点为中心形成的四种田字阵型
func (sc *serverControl) CheckDaLianKill(points []proto.ChessPoint) int {
	daLianKillCount := 0
	if len(points) == 1 {
		return daLianKillCount
	}
	targetPoint := points[len(points)-1]
	chessData := ServerModel.ChessData
	if chessData[targetPoint.Row][targetPoint.Col] != ChessPieces_NONE {
		return daLianKillCount
	}
	piecesType := chessData[targetPoint.Row][targetPoint.Col]
	rows := len(chessData)
	cols := len(chessData[0])
	checkPoint := func(p *proto.ChessPoint) bool {
		if p.Col < 0 || p.Col >= cols || p.Row >= rows || p.Row < 0 {
			return false
		}
		return true
	}
	checkModel := func(p1, p2, p3 *proto.ChessPoint) {
		if !checkPoint(p1) || !checkPoint(p2) || !checkPoint(p3) {
			return
		}
		if chessData[p1.Row][p1.Col] == piecesType &&
			chessData[p2.Row][p2.Col] == piecesType &&
			chessData[p3.Row][p3.Col] == piecesType {
			daLianKillCount++
		}
	}
	//右下
	checkModel(&proto.ChessPoint{Row: targetPoint.Row + 1, Col: targetPoint.Col},
		&proto.ChessPoint{Row: targetPoint.Row, Col: targetPoint.Col + 1},
		&proto.ChessPoint{Row: targetPoint.Row + 1, Col: targetPoint.Col + 1})
	//左下
	checkModel(&proto.ChessPoint{Row: targetPoint.Row - 1, Col: targetPoint.Col},
		&proto.ChessPoint{Row: targetPoint.Row - 1, Col: targetPoint.Col + 1},
		&proto.ChessPoint{Row: targetPoint.Row, Col: targetPoint.Col + 1})
	//右上
	checkModel(&proto.ChessPoint{Row: targetPoint.Row, Col: targetPoint.Col - 1},
		&proto.ChessPoint{Row: targetPoint.Row + 1, Col: targetPoint.Col - 1},
		&proto.ChessPoint{Row: targetPoint.Row + 1, Col: targetPoint.Col})
	//左上
	checkModel(&proto.ChessPoint{Row: targetPoint.Row, Col: targetPoint.Col - 1},
		&proto.ChessPoint{Row: targetPoint.Row - 1, Col: targetPoint.Col - 1},
		&proto.ChessPoint{Row: targetPoint.Row - 1, Col: targetPoint.Col})

	return daLianKillCount
}

// 褡裢吃子
func (sc *serverControl) DaLianKill(killPoints []proto.ChessPoint, piecesType int) bool {
	chessData := ServerModel.ChessData
	for i := 0; i < len(killPoints); i++ {
		if chessData[killPoints[i].Row][killPoints[i].Col] == ChessPieces_NONE ||
			chessData[killPoints[i].Row][killPoints[i].Col] == piecesType {
			log.ErrLog("吃子为空，或者是自己的子 %s, %s", utils.Struct2JSON(killPoints), utils.Struct2JSON(ServerModel.ChessData))
			return false
		}
		chessData[killPoints[i].Row][killPoints[i].Col] = ChessPieces_NONE
	}
	return true
}
